package com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.displaylabels.fourbytwo;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;

import com.nickstumpos.android.GmailWidgetPlus.Constants.GMWP_Constants;
import com.nickstumpos.android.GmailWidgetPlus.gmailProvider.GmailProvider;
import com.nickstumpos.android.GmailWidgetPlus.labels.LabelCountPair;
import com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.SimpleLabel;
import com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.WidgetUIData;
import com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.WidgetUIManager;
import com.nickstumpos.android.GmailWidgetPlus.widget.skins.WidgetSkin;
import com.nickstumpos.android.GmailWidgetPlus.widget.skins.WidgetSkins;

public abstract class FourByTwoWidgetUIManager implements WidgetUIManager {

	private RemoteViews					widgetLayout	= null;
	private final Context				context;
	private Map<WidgetSkin, Integer>	startIndex;
	private List<LabelCountPair>		labels;
	final List<SimpleLabel>				labelViewData;
	private final WidgetUIData			wData;
	private boolean						haveAccount;

	public FourByTwoWidgetUIManager(final Context context,
			final WidgetUIData wData) {
		this.labelViewData = new ArrayList<SimpleLabel>();
		this.context = context;
		this.wData = wData;
		this.initMaps();
		this.addLabelViewData();
		this.initMainButtonIntents();

	}

	protected abstract void addLabelViewData();

	protected Boolean changeCurrentStartIndex(final int delta) {

		Boolean ret = false;
		if ((this.wData != null) && (this.wData.getSkin() != null)
				&& (this.labels != null)
				&& (this.startIndex != null)) {
			final int possibleValue = this.getCurrentStartIndex() + delta;
			if ((possibleValue >= 0) && (possibleValue + this.wData.getSkin()
					.totalShowingLabels() <= this.labels.size())) {
				this.startIndex.put(this.wData.getSkin(),
						this.getCurrentStartIndex() + delta);
				ret = true;
			}
		}
		return ret;
	}

	protected void changeToStateIsUnread(final List<LabelCountPair> labels) {

		this.getRemoteViews()
				.setViewVisibility(this.wData.getUnreadCountButton(),
						View.VISIBLE);
		this.getRemoteViews()
				.setViewVisibility(this.wData.getNoUnreadMailButton(),
						View.GONE);
		for (final SimpleLabel label : this.getLabelViewData()) {
			final int loc = label.getPosition() + this.getCurrentStartIndex();
			if (loc < labels.size()) {
				this.getRemoteViews().setTextViewText(label.getLabelViewID(),
						labels.get(loc).toString());
				this.getRemoteViews().setTextViewText(label.getUnreadViewID(),
						"(" + labels.get(loc).getCount() + ")");
				this.getRemoteViews()
						.setOnClickPendingIntent(label.getOuterId(),
								PendingIntent.getActivity(this.getContext(),
										(int) Calendar.getInstance()
												.getTimeInMillis() << 4,
										GmailProvider.getGmailAvailable(this.context)
												.putExtra(GMWP_Constants.EXTRA_GMAIL_LABEL,
														labels.get(loc)
																.getLabel())
												.putExtra(GMWP_Constants.EXTRA_GMAIL_ACCOUNT,
														FourByTwoWidgetUIManager.this.wData.getAccount()),
										0));
				this.showLabel(label);
			} else {
				this.hideLabel(label);
			}
		}
	}

	protected void changeToStateNoAccount() {

		this.getRemoteViews().setTextViewText(this.wData.getNoUnreadMailText(),
				GMWP_Constants.NO_ACCT_MSG);
		this.getRemoteViews()
				.setViewVisibility(this.wData.getNoUnreadMailButton(),
						View.VISIBLE);
		this.getRemoteViews()
				.setOnClickPendingIntent(this.wData.getNoUnreadMailButton(),
						PendingIntent.getActivity(this.getContext(),
								(int) Calendar.getInstance().getTimeInMillis() << 4,
								new Intent(),
								0));
		this.hideAllLabels();
		this.getRemoteViews()
				.setViewVisibility(this.wData.getUnreadCountButton(), View.GONE);
	}

	protected void changeToStateNoUnread() {

		this.getRemoteViews()
				.setViewVisibility(this.wData.getUnreadCountButton(),
						View.VISIBLE);
		this.setArrowButtonStates();
		this.getRemoteViews().setTextViewText(this.wData.getNoUnreadMailText(),
				GMWP_Constants.NO_UNREAD_MSG);
		this.getRemoteViews()
				.setViewVisibility(this.wData.getNoUnreadMailButton(),
						View.VISIBLE);
		this.hideAllLabels();
		this.getRemoteViews()
				.setOnClickPendingIntent(this.wData.getNoUnreadMailButton(),
						PendingIntent.getActivity(this.getContext(),
								(int) Calendar.getInstance().getTimeInMillis() << 4,
								GmailProvider.getGmailAvailable(this.context)
										.putExtra(GMWP_Constants.EXTRA_GMAIL_LABEL,
												"^i")
										.putExtra(GMWP_Constants.EXTRA_GMAIL_ACCOUNT,
												FourByTwoWidgetUIManager.this.wData.getAccount())

								,
								0));
	}

	protected void changeWidgetState() {

		if (this.labels != null) {
			Log.i("GMWP", "Changing state of widget: " + this.getWidgetId());
			if (!this.haveAccount) {
				this.changeToStateNoAccount();
			} else {
				if (this.labels.size() == 0) {
					this.changeToStateNoUnread();
				} else {
					this.changeToStateIsUnread(this.labels);
				}
				this.setArrowButtonStates();
			}
			this.commitUpdate();
		} else {
			Log.e("GMWP", "Label list not initialised");
		}
	}

	private void commitUpdate() {

		final AppWidgetManager manager = AppWidgetManager.getInstance(this.getContext());
		manager.updateAppWidget(this.wData.getWidgetId(), this.getRemoteViews());
		this.widgetLayout = null;
	}

	/**
	 * @return the account
	 */
	protected String getAccount() {

		return this.wData.getAccount();
	}

	protected String getActionToUpdate() {

		final String action;
		switch (this.wData.getSize()) {
			case FOURxTWO:
				action = GMWP_Constants.ACTION_GWID_UPDATE_FBT;
				break;
			case TWOxTWO:
				action = GMWP_Constants.ACTION_GWID_UPDATE_TBT;
				break;
			default:
				action = GMWP_Constants.ACTION_GWID_UPDATE_TBT;
		}
		return action;
	}

	public Context getContext() {

		return this.context;
	}

	protected int getCurrentStartIndex() {
		int ret = 0;
		if ((this.wData != null) && (this.startIndex != null)
				&& (this.wData.getSkin() != null)) {
			ret = this.startIndex.get(this.wData.getSkin());
		}
		return ret;
	}

	/**
	 * @return the labels
	 */
	protected List<LabelCountPair> getLabels() {

		return this.labels;
	}

	/**
	 * @return the labelViewData
	 */
	protected List<SimpleLabel> getLabelViewData() {

		return this.labelViewData;
	}

	protected RemoteViews getRemoteViews() {

		if (this.widgetLayout == null) {
			this.widgetLayout = new RemoteViews(this.getContext()
					.getPackageName(), this.wData.getSkin().getLayout());
		}
		return this.widgetLayout;
	}

	/**
	 * @return the widgetId
	 */
	protected int getWidgetId() {

		return this.wData.getWidgetId();
	}

	protected Boolean hasMoreLabelsAhead() {

		if (this.getCurrentStartIndex() + this.wData.getSkin()
				.totalShowingLabels() < this.labels.size()) {
			return true;
		}
		return false;
	}

	protected Boolean hasMoreLabelsBehind() {

		if ((this.getCurrentStartIndex() > 0) && (this.wData.getSkin()
				.totalShowingLabels() < this.labels.size())) {
			return true;
		}
		return false;
	}

	protected void hideAllLabels() {

		for (final SimpleLabel label : this.getLabelViewData()) {
			this.hideLabel(label);
		}
	}

	protected void hideLabel(final SimpleLabel label) {

		this.getRemoteViews().setViewVisibility(label.getOuterId(), View.GONE);
		this.getRemoteViews().setViewVisibility(label.getLabelViewID(),
				View.GONE);
		this.getRemoteViews().setViewVisibility(label.getHrID(), View.GONE);
		this.getRemoteViews().setViewVisibility(label.getUnreadViewID(),
				View.GONE);
	}

	protected abstract void initAdditionalButtonIntents();

	protected void initMainButtonIntents() {

		this.getRemoteViews()
				.setOnClickPendingIntent(this.wData.getUnreadCountButton(),
						PendingIntent.getActivity(this.getContext(),
								(int) Calendar.getInstance().getTimeInMillis() << 4,
								GmailProvider.getGmailAvailable(this.context)
										.setAction(GMWP_Constants.ACTION_GMAIL_SEARCH)
										.putExtra(GMWP_Constants.EXTRA_GMAIL_QUERY,
												GMWP_Constants.GMAIL_UNREAD_QUERY)
										.putExtra(GMWP_Constants.EXTRA_GMAIL_ACCOUNT,
												FourByTwoWidgetUIManager.this.wData.getAccount())

								,
								0));
		this.getRemoteViews()
				.setOnClickPendingIntent(this.wData.getDownButton(),
						PendingIntent.getBroadcast(this.getContext(),
								(int) Calendar.getInstance().getTimeInMillis() << 4,
								new Intent() {

									{
										this.setAction(FourByTwoWidgetUIManager.this.getActionToUpdate());
										this.putExtra(GMWP_Constants.EXTRA_WIDGET_ACTION,
												GMWP_Constants.WIDGET_DN);
										this.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
												FourByTwoWidgetUIManager.this.wData.getWidgetId());
									}
								},
								0));
		this.getRemoteViews().setOnClickPendingIntent(this.wData.getUpButton(),
				PendingIntent.getBroadcast(this.getContext(),
						(int) Calendar.getInstance().getTimeInMillis() << 4,
						new Intent() {

							{
								this.setAction(FourByTwoWidgetUIManager.this.getActionToUpdate());
								this.putExtra(GMWP_Constants.EXTRA_WIDGET_ACTION,
										GMWP_Constants.WIDGET_UP);
								this.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
										FourByTwoWidgetUIManager.this.wData.getWidgetId());
							}
						},
						0));
		this.initAdditionalButtonIntents();
	}

	private void initMaps() {

		this.startIndex = new HashMap<WidgetSkin, Integer>();
		for (final WidgetSkins t : WidgetSkins.values()) {
			this.startIndex.put(t, 0);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.
	 * WidgetUIManager#nextLabelSet()
	 */
	@Override
	public abstract void nextLabelSet();

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.
	 * WidgetUIManager#previousLabelSet()
	 */
	@Override
	public abstract void previousLabelSet();

	/**
	 * @param account
	 *            the account to set
	 */
	protected void setAccount(final String account) {

		this.wData.setAccount(account);
	}

	protected void setArrowButtonStates() {

		if (this.hasMoreLabelsBehind()) {
			this.getRemoteViews()
					.setViewVisibility(this.wData.getUpButtonDisabled(),
							View.GONE);
			this.getRemoteViews().setViewVisibility(this.wData.getUpButton(),
					View.VISIBLE);
		} else {
			this.getRemoteViews().setViewVisibility(this.wData.getUpButton(),
					View.GONE);
			this.getRemoteViews()
					.setViewVisibility(this.wData.getUpButtonDisabled(),
							View.VISIBLE);
		}
		if (this.hasMoreLabelsAhead()) {
			this.getRemoteViews().setViewVisibility(this.wData.getDownButton(),
					View.VISIBLE);
			this.getRemoteViews()
					.setViewVisibility(this.wData.getDownButtonDisabled(),
							View.GONE);
		} else {
			this.getRemoteViews().setViewVisibility(this.wData.getDownButton(),
					View.GONE);
			this.getRemoteViews()
					.setViewVisibility(this.wData.getDownButtonDisabled(),
							View.VISIBLE);
		}
	}

	/**
	 * @param labels
	 *            the labels to set
	 */
	protected void setLabels(final List<LabelCountPair> labels) {

		this.labels = labels;
	}

	/**
	 * @param widgetId
	 *            the widgetId to set
	 */
	protected void setWidgetId(final int widgetId) {

		this.wData.setWidgetId(widgetId);
	}

	protected void showLabel(final SimpleLabel label) {

		this.getRemoteViews().setViewVisibility(label.getOuterId(),
				View.VISIBLE);
		this.getRemoteViews().setViewVisibility(label.getLabelViewID(),
				View.VISIBLE);
		this.getRemoteViews().setViewVisibility(label.getHrID(), View.VISIBLE);
		this.getRemoteViews().setViewVisibility(label.getUnreadViewID(),
				View.VISIBLE);
	}

	protected void updateUnreadCount(final int unreadCount) {

		this.getRemoteViews()
				.setTextViewText(this.wData.getUnreadCountButton(),
						String.valueOf(unreadCount));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.
	 * WidgetUIManager#updateWidget(java.util.List, int, boolean)
	 */
	@Override
	public void updateWidget(final List<LabelCountPair> labels,
			final int unreadCount,
			final boolean haveAccount) {

		Log.i("GMWP", "updating Widget: " + this.getWidgetId());
		this.labels = labels;
		this.haveAccount = haveAccount;
		this.updateUnreadCount(unreadCount);
		this.changeWidgetState();
	}
}
